﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.IO;
using System.Reflection;
using System.Security;
using System.Xml;
using System.Xml.XPath;

namespace TeamReview.SetupRegistrationAction
{
    [RunInstaller(true)]
    public class InstallerTeamReview : Installer
    {
        private const string AddinName = @"TeamReview.VSNetAddIn.Addin";

        public override void Install(IDictionary stateSaver)
        {
            base.Install(stateSaver);
            
            Assembly asm = Assembly.GetExecutingAssembly();

            // get directory name of install directory
            string fileName = Path.Combine(Path.GetDirectoryName(asm.Location), AddinName);

            FileInfo fInfo = new FileInfo(fileName);

            if (!fInfo.Exists)
                throw new FileNotFoundException(string.Format("File '{0}' is not found. Installation will be aborted or not complete.", fileName));

            try
            {
                // Load the .Addin file into XML document
                XmlDocument doc = new XmlDocument();
                doc.Load(fInfo.FullName);

                XPathNavigator navigator = doc.CreateNavigator();
                XmlNamespaceManager nsmgr = new XmlNamespaceManager(navigator.NameTable);
                nsmgr.AddNamespace("ae", "http://schemas.microsoft.com/AutomationExtensibility");

                XmlElement root = doc.DocumentElement;
                if (root == null) throw new XmlSyntaxException("Addin XML Root element definition");

                var assemblyNode = root.SelectSingleNode("/ae:Extensibility/ae:Addin/ae:Assembly", nsmgr);
                if (assemblyNode == null)
                {
                    throw new XmlSyntaxException(
                        "XML File is missing the Assembly Element, installation is not complete");
                }

                assemblyNode.InnerText = Path.ChangeExtension(fileName, "dll");

                // Save the updated xml in the destination .addin File
                string folderPath = AddinFolderPath();

                DirectoryInfo dirInfo = new DirectoryInfo(folderPath);
                if (!dirInfo.Exists)
                    dirInfo.Create();

                string destFile =  Path.Combine(folderPath, AddinName);
                doc.Save(destFile);
            }
            catch (Exception ex)
            {
                throw new Exception(
                    string.Format(
                        "Failure to process file '{0}'. Error= {1}. Installation will be aborted or not complete.",
                        fInfo.FullName, ex), ex);
            }
        }

        /// <summary>
        /// ["ALLUSERS"] is passed via the customactiondata in the setup project
        /// if ["ALLUSERS"] is not set or ="2", do a per user install
        /// see http://msdn.microsoft.com/en-us/library/aa367559(VS.85).aspx
        /// </summary>
        /// <returns>
        /// Path to C:\Documents and Settings\<user>\Application Data\Microsoft\MSEnvShared\Addins
        /// </returns>
        private string AddinFolderPath()
        {
            string alluser = this.Context.Parameters["ALLUSERS"];

            if (string.IsNullOrEmpty(alluser) || (string.Compare(alluser, "2") == 0))
            {
                return string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
                            , @"\Microsoft\MSEnvShared\Addins");
            }

            return  string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)
                                  , @"\Microsoft\MSEnvShared\Addins");
        }

        public override void Uninstall(IDictionary savedState)
        {
            base.Uninstall(savedState);

            try
            {
                string folderPath = AddinFolderPath();
                DirectoryInfo dirInfo = new DirectoryInfo(folderPath);
                if (dirInfo.Exists)
                {
                    string destFile = Path.Combine(folderPath, AddinName);
                    File.Delete(destFile);

                    File.Delete(Path.Combine(folderPath, @"TeamReview.config"));
                    File.Delete(Path.Combine(folderPath, @"TeamReview.log"));
                }
            }
            catch 
            {
            }
        }
    }
}
